<?php
class HtmlCommon {
	/**
	 +----------------------------------------------------------
	 * 输出安全的html，用于过滤危险代码
	 +----------------------------------------------------------
	 * @access public
	 +----------------------------------------------------------
	 * @param string $text 要处理的字符串
	 * @param mixed $allowTags 允许的标签列表，如 table|td|th|td
	 +----------------------------------------------------------
	 * @return string
	 +----------------------------------------------------------
	 */
	static public function safeHtml($text, $allowTags = null) {
		$text	=	trim($text);
		$text	=	preg_replace('/<!--?.*-->/','',$text);
		//完全过滤注释
		$text	=	preg_replace('/<!--?.*-->/','',$text);
		//完全过滤动态代码
		$text	=	preg_replace('/<\?|\?'.'>/','',$text);
		//完全过滤js
		$text	=	preg_replace('/<script?.*\/script>/','',$text);
	
		$text	=	str_replace('[','&#091;',$text);
		$text	=	str_replace(']','&#093;',$text);
		$text	=	str_replace('|','&#124;',$text);
		//过滤换行符
		$text	=	preg_replace('/\r?\n/','',$text);
		//br
		$text	=	preg_replace('/<br(\s\/)?'.'>/i','[br]',$text);
		$text	=	preg_replace('/(\[br\]\s*){10,}/i','[br]',$text);
		//过滤危险的属性，如：过滤on事件lang js
		while(preg_match('/(<[^><]+) (lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i',$text,$mat)){
			$text=str_replace($mat[0],$mat[1],$text);
		}
		while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){
			$text=str_replace($mat[0],$mat[1].$mat[3],$text);
		}
		if(empty($tags)) {
			$tags = 'table|tbody|td|th|tr|i|b|u|strong|img|p|br|div|span|em|ul|ol|li|dl|dd|dt|a|alt|h[1-9]?';
			$tags.= '|object|param|embed';	// 音乐和视频
		}
		//允许的HTML标签
		$text	=	preg_replace('/<(\/?(?:'.$tags.'))( [^><\[\]]*)?>/i','[\1\2]',$text);
		//过滤多余html
		$text	=	preg_replace('/<\/?(html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|style|xml)[^><]*>/i','',$text);
		//过滤合法的html标签
		while(preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i',$text,$mat)){
			$text=str_replace($mat[0],str_replace('>',']',str_replace('<','[',$mat[0])),$text);
		}
		//转换引号
		while(preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2\[\]]+)\2([^\[\]]*\])/i',$text,$mat)){
			$text = str_replace($mat[0], $mat[1] . '|' . $mat[3] . '|' . $mat[4],$text);
		}
		//过滤错误的单个引号
		// 修改:2011.05.26 kissy编辑器中表情等会包含空引号, 简单的过滤会导致错误
		while(preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i',$text,$mat)){
			$text=str_replace($mat[0],str_replace($mat[1],'',$mat[0]),$text);
		}
		//转换其它所有不合法的 < >
		$text	=	str_replace('<','&lt;',$text);
		$text	=	str_replace('>','&gt;',$text);
		$text   =   str_replace('"','&quot;',$text);
		$text   =   str_replace('\\','',$text);
		$text	=	str_replace('&lt;o:p&gt;&lt;/o:p&gt;', '', $text);
		//反转换
		$text	=	str_replace('[','<',$text);
		$text	=	str_replace(']','>',$text);
		$text	=	str_replace('|','"',$text);
		//过滤多余空格
		$text	=	str_replace('  ',' ',$text);
		return $text;
	}
	
	/**
	 * 转换为安全的纯文本
	 *
	 * @param string  $text
	 * @param boolean $parse_br    是否转换换行符
	 * @param int     $quote_style ENT_NOQUOTES:(默认)不过滤单引号和双引号 ENT_QUOTES:过滤单引号和双引号 ENT_COMPAT:过滤双引号,而不过滤单引号
	 * @return string|null string:被转换的字符串 null:参数错误
	 */
	function text($text, $parse_br = false, $quote_style = ENT_NOQUOTES){
		if (is_numeric($text))
			$text = (string)$text;
	
		if (!is_string($text))
			return null;
	
		if (!$parse_br) {
			$text = str_replace(array("\r","\n","\t"), ' ', $text);
		} else {
			$text = nl2br($text);
		}
	
		$text = htmlspecialchars($text, $quote_style, 'UTF-8');
	
		return $text;
	}
	
	function safe($text,$type='html',$tagsMethod=true,$attrMethod=true,$xssAuto = 1,$tags=array(),$attr=array(),$tagsBlack=array(),$attrBlack=array()){
	
		//无标签格式
		$text_tags	=	'';
	
		//只存在字体样式
		$font_tags	=	'<i><b><u><s><em><strong><font><big><small><sup><sub><bdo><h1><h2><h3><h4><h5><h6>';
	
		//标题摘要基本格式
		$base_tags	=	$font_tags.'<p><br><hr><a><img><map><area><pre><code><q><blockquote><acronym><cite><ins><del><center><strike>';
	
		//兼容Form格式
		$form_tags	=	$base_tags.'<form><input><textarea><button><select><optgroup><option><label><fieldset><legend>';
	
		//内容等允许HTML的格式
		$html_tags	=	$base_tags.'<ul><ol><li><dl><dd><dt><table><caption><td><th><tr><thead><tbody><tfoot><col><colgroup><div><span><object><embed><param>';
	
		//专题等全HTML格式
		$all_tags	=	$form_tags.$html_tags.'<!DOCTYPE><html><head><title><body><base><basefont><script><noscript><applet><object><param><style><frame><frameset><noframes><iframe>';
	
		//过滤标签
		$text	=	strip_tags($text, ${$type.'_tags'} );
	
		//过滤攻击代码
		if($type!='all'){
			//过滤危险的属性，如：过滤on事件lang js
			while(preg_match('/(<[^><]+) (onclick|onload|unload|onmouseover|onmouseup|onmouseout|onmousedown|onkeydown|onkeypress|onkeyup|onblur|onchange|onfocus|action|background|codebase|dynsrc|lowsrc)([^><]*)/i',$text,$mat)){
				$text	=	str_ireplace($mat[0],$mat[1].$mat[3],$text);
			}
			while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){
				$text	=	str_ireplace($mat[0],$mat[1].$mat[3],$text);
			}
		}
		return $text;
	}
	
	//输出纯文本
	function texts($text,$parseBr=false){
		$text = htmlspecialchars_decode($text);
		$text = common('Html')->safe($text,'text');
		if(!$parseBr){
			$text	=	str_ireplace(array("\r","\n","\t","&nbsp;"),'',$text);
			$text	=	htmlspecialchars($text,ENT_QUOTES);
		}else{
			$text	=	htmlspecialchars($text,ENT_QUOTES);
			$text	=	nl2br($text);
		}
		$text	=	trim($text);
		return $text;
	}
	
	//取消HTML代码
	function shtmlspecialchars($string) {
		if(is_array($string)) {
			foreach($string as $key => $val) {
				$string[$key] = shtmlspecialchars($val);
			}
		} else {
			$string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/', '&\\1',
					str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $string));
		}
		return $string;
	}
	
	/**
	 * 锁定表单
	 *
	 * @param int $life_time 表单锁的有效时间(秒). 如果有效时间内未解锁, 表单锁自动失效.
	 * @return boolean 成功锁定时返回true, 表单锁已存在时返回false
	 */
	function lockSubmit($life_time = null) {
		if (isset ($_SESSION['LOCK_SUBMIT_TIME']) && intval($_SESSION['LOCK_SUBMIT_TIME']) > time()) {
			return false;
		} else {
			$life_time = $life_time ? $life_time : $GLOBALS['yl']['site']['max_post_time'];
			$_SESSION['LOCK_SUBMIT_TIME'] = time() + intval($life_time);
			return true;
		}
	}
	
	/**
	 * 检查表单是否已锁定
	 *
	 * @return boolean 表单已锁定时返回true, 否则返回false
	 */
	function isSubmitLocked() {
		return isset ($_SESSION['LOCK_SUBMIT_TIME']) && intval($_SESSION['LOCK_SUBMIT_TIME']) > time();
	}
	
	/**
	 * 检查表单是否已锁定
	 *
	 * @return boolean 表单已锁定时返回true, 否则返回false
	 */
	function isDuplicateContent($content) {
		$content = md5($content);
		$res = ($_SESSION['LOCK_SUBMIT_CONTENT'] === $content);
		if (!$res) {
			$_SESSION['LOCK_SUBMIT_CONTENT'] = $content;
		}
		return $res;
	}
}
?>